package com.horatio.db;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jolbox.bonecp.BoneCP;
import com.jolbox.bonecp.BoneCPConfig;

/**
 * DB链接池工厂
 * @author hongxiao.z
 * @date   2014-5-16  下午7:43:58
 */
public class DBDataSourceFactory 
{
	private static Map<String, BoneCP> map = new HashMap<>();
	
	private static Logger log = LoggerFactory.getLogger(DBDataSourceFactory.class);
	
	/**
	 * 获取数据库链接
	 * @param key
	 * @return
	 * @create	hongxiao.z      2014-5-16 下午8:54:24
	 */
	public static Connection getConnection(String key)
	{
		BoneCP bone = map.get(key);
		
		try {
			return bone.getConnection();
		} catch (SQLException e) 
		{
			log.error(key + "的链接不存在!");
			return null;
		}
	}
	
	/**
	 * 初始化一个连接池
	 * @param key
	 * @param path
	 * @create	hongxiao.z      2014-5-16 下午8:00:24
	 */
	private static void initDataSource(String key, String path)
	{
		DBDataConfig configData = null;
		try 
		{
			configData = new DBDataConfig(path);
		} 
		catch (Exception e) 
		{
			log.error(" >>> DB链接配置错误！", e);
		}
		
		//一些参数设置
		BoneCPConfig config = new BoneCPConfig();    // create a new configuration object
	        // set the JDBC url
		
		try {
			Class.forName(configData.driver);
		} catch (ClassNotFoundException e1) {
			log.error(" >>> DB地址驱动出错！", e1);
		}
		
        config.setJdbcUrl(configData.url);
        config.setUsername(configData.user);            // set the username
        config.setPassword(configData.password);                // set the password
        config.setPartitionCount(Integer.parseInt(configData.partitionCount));
        config.setMaxConnectionsPerPartition(Integer.parseInt(configData.maxConnections));
        config.setMinConnectionsPerPartition(Integer.parseInt(configData.minConnections));
        config.setAcquireIncrement(Integer.parseInt(configData.acquireIncrement));
        config.setPoolAvailabilityThreshold(Integer.parseInt(configData.poolavailabilitythreshold));
        config.setIdleMaxAge(Long.parseLong(configData.idlemaxage), TimeUnit.MINUTES);
        config.setIdleConnectionTestPeriod(Long.parseLong(configData.idleconnectiontestperiod),TimeUnit.MINUTES);
        config.setStatementsCacheSize(Integer.parseInt(configData.statementscachesize));
//	    config.setStatementReleaseHelperThreads(3);
//	    config.setReleaseHelperThreads(2);
        
        try 
        {
        	BoneCP connPool = new BoneCP(config);
        	map.put(key, connPool);
		} catch (SQLException e) {
			log.error("BoneCP 初始化失败！", e);
		} 
        
        
	}
	
	/**
	 * 配置
	 * @author hongxiao.z
	 * @date   2014-5-16  下午7:57:15
	 */
	private static class DBDataConfig
	{
		private final String driver;
		private final String url; 		
		private final String user; 			
		private final String password; 		
		private final String partitionCount;
		private final String maxConnections;
		private final String minConnections;
		private final String acquireIncrement;
		private final String poolavailabilitythreshold;
//		private final String releasehelperthreads;
		private final String idlemaxage;
		private final String idleconnectiontestperiod;
		private final String statementscachesize;
//		private final String statementreleasehelperthreads;		
		
		
		private DBDataConfig(String path) throws Exception
		{
			Properties p = new Properties();
			FileInputStream fis;
			
			fis = new FileInputStream(path);
			p.load(fis);
			fis.close();
			
			driver 							= p.getProperty("driver");
			url 							= p.getProperty("url");
			user 							= p.getProperty("user");
			password 						= p.getProperty("password");
			partitionCount 					= p.getProperty("partition.count");
			maxConnections 					= p.getProperty("max.connections");
			minConnections 					= p.getProperty("min.connections");
			acquireIncrement 				= p.getProperty("acquire.increment");
			poolavailabilitythreshold 		= p.getProperty("poolavailabilitythreshold");
//			releasehelperthreads 			= p.getProperty("releasehelperthreads");
			idlemaxage 						= p.getProperty("idlemaxage");
			idleconnectiontestperiod 		= p.getProperty("idleconnectiontestperiod");
			statementscachesize 			= p.getProperty("statementscachesize");
//			statementreleasehelperthreads 	= p.getProperty("statementreleasehelperthreads");
		}
	}
	
	public static final String AI_KEY = "AI";
	static //初始化
	{
		initDataSource(AI_KEY, "AIDB.properties");
	}
}
